/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.listener;

import cn.easyplatform.lang.Files;
import cn.easyplatform.lang.Streams;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.request.LoginRequestMessage;
import cn.easyplatform.messages.request.SimpleRequestMessage;
import cn.easyplatform.messages.response.LoginResponseMessage;
import cn.easyplatform.messages.vos.AuthorizationVo;
import cn.easyplatform.messages.vos.EnvVo;
import cn.easyplatform.messages.vos.LoginVo;
import cn.easyplatform.spi.service.IdentityService;
import cn.easyplatform.type.Constants;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.UserType;
import cn.easyplatform.web.WebApps;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.service.ServiceLocator;
import org.apache.commons.lang3.StringUtils;
import org.zkoss.util.resource.Labels;
import org.zkoss.web.Attributes;
import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Captcha;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Textbox;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class LoginListener implements EventListener<Event> {

    private EnvVo env;

    private Component cmd;

    private LoginVo vo;

    public LoginListener(EnvVo env) {
        this.env = env;
    }

    @Override
    public void onEvent(Event event) throws Exception {
        if (event.getData() == null) {
            Textbox userBox = (Textbox) event.getTarget().getFellow("userId");
            Textbox passwordBox = (Textbox) event.getTarget().getFellow(
                    "userPassword");
            if (Strings.isBlank(userBox.getText())) {
                userBox.setErrorMessage(Labels
                        .getLabel("user.name.placeholder"));
                userBox.setFocus(true);
                return;
            }
            if (Strings.isBlank(passwordBox.getText())) {
                passwordBox.setFocus(true);
                passwordBox.setErrorMessage(Labels
                        .getLabel("user.password.placeholder"));
                return;
            }
            //是否有验证码
            Textbox captcha = (Textbox) event.getTarget().getFellowIfAny("captcha");
            if (captcha != null) {
                Captcha cp = (Captcha) event.getTarget().getRoot().query("captcha");
                if (cp != null) {
                    if (Strings.isBlank(captcha.getValue())) {
                        captcha.setFocus(true);
                        captcha.setErrorMessage(Labels
                                .getLabel("user.captcha.placeholder"));
                        return;
                    }
                    if (!cp.getValue().equalsIgnoreCase(captcha.getValue())) {
                        captcha.setFocus(true);
                        captcha.setErrorMessage(Labels
                                .getLabel("user.captcha.match"));
                        cp.randomValue();
                        return;
                    }
                }
            }
            IdentityService uc = ServiceLocator
                    .lookup(IdentityService.class);
            vo = new LoginVo();
            vo.setIp(WebApps.getRemoteAddr((HttpServletRequest) Executions.getCurrent()
                    .getNativeRequest()));
            vo.setLocale(Sessions.getCurrent()
                    .getAttribute(Attributes.PREFERRED_LOCALE).toString());
            vo.setId(userBox.getText());
            vo.setPassword(passwordBox.getText());
            LoginRequestMessage req = new LoginRequestMessage(vo);
            IResponseMessage<?> resp = uc.login(req);
            if (resp.isSuccess()) {
                doLogin(resp, event.getPage());
            } else if (resp.getCode().equals("C000")) {
                cmd = event.getTarget();
                Messagebox.show((String) resp.getBody(), resp.getCode(),
                        Messagebox.CANCEL | Messagebox.OK, Messagebox.QUESTION,
                        this);
            } else if (resp.getCode().equals("E000")) {// 服务器的会话超时
                Sessions.getCurrent().removeAttribute(Constants.SESSION_ID);
                resp = uc.getAppEnv(new SimpleRequestMessage(env));
                if (resp.isSuccess()) {
                    env = (EnvVo) resp.getBody();
                    Sessions.getCurrent().setAttribute(Constants.SESSION_ID, env.getSessionId());
                    onEvent(event);
                }
            } else {
                // ((Label) event.getTarget().getFellow("errMsg"))
                // .setValue((String) resp.getBody());
                Clients.wrongValue(event.getTarget(), (String) resp.getBody());
            }
        } else {
            int type = (Integer) event.getData();
            IdentityService uc = ServiceLocator
                    .lookup(IdentityService.class);
            IResponseMessage<?> resp = uc.confirm(new SimpleRequestMessage(
                    type == Messagebox.OK));
            if (resp.isSuccess()) {
                if (type == Messagebox.OK)
                    doLogin(resp, event.getPage());
            } else {
                // errLabel.setValue((String) resp.getBody());
                Clients.wrongValue(cmd, (String) resp.getBody());
            }
        }
    }

    private void doLogin(IResponseMessage<?> rp, Page page) {
        Session session = page.getDesktop().getSession();
        if (rp instanceof LoginResponseMessage) {
            LoginResponseMessage resp = (LoginResponseMessage) rp;
            session.setAttribute(Contexts.PLATFORM_USER, vo);
            vo.setType(resp.getType());
            vo.setTooltip(resp.getTooltip());
            vo.setName(resp.getName());
            if (resp.getBody() instanceof List<?>) {
                Map<String, Object> args = new HashMap<String, Object>(1);
                args.put("orgs", resp.getBody());
                args.put("vo", vo);
                Executions.createComponents("~./pages/org.zul", null, args);
            } else if (resp.getBody() instanceof AuthorizationVo) {
                vo.setOrgId(resp.getOrgId());
                AuthorizationVo av = (AuthorizationVo) resp.getBody();
                if (vo.getType() == UserType.TYPE_ADMIN)
                    env.setMainPage(Streams.readAndClose(Streams.utf8r(Files
                            .findFileAsStream("web/admin/admin.zul"))));
                else
                    env.setMainPage(av.getMainPage());
                session.setAttribute(Contexts.PLATFORM_USER_AUTHORIZATION, av);
                Executions.sendRedirect("/main.go");
            } else {
                env.setMainPage((String) resp.getBody());
                if (session.getAttribute(Contexts.PLATFORM_USER_AUTHORIZATION) != null)
                    Executions.sendRedirect("/main.go");
            }
        } else {
            Map<String, Object> args = new HashMap<String, Object>(1);
            args.put("phone", rp.getBody());
            args.put("vo", vo);
            args.put("env", env);
            Executions.createComponents("~./pages/phone.zul", null, args);
        }
    }
}
